<template>
  <!-- 进阶绘制示例：测距、矩形、圆、椭圆、多边形 -->
  <div class="page-wrap">
    <div class="toolbar">
      <el-button-group>
        <el-button
          size="small"
          :type="mode === 'measure' ? 'primary' : 'default'"
          @click="setMode('measure')"
          >测距</el-button
        >
        <el-button
          size="small"
          :type="mode === 'rectangle' ? 'primary' : 'default'"
          @click="setMode('rectangle')"
          >画矩形</el-button
        >
        <el-button
          size="small"
          :type="mode === 'circle' ? 'primary' : 'default'"
          @click="setMode('circle')"
          >画圆</el-button
        >
        <el-button
          size="small"
          :type="mode === 'ellipse' ? 'primary' : 'default'"
          @click="setMode('ellipse')"
          >画椭圆</el-button
        >
        <el-button
          size="small"
          :type="mode === 'polygon' ? 'primary' : 'default'"
          @click="setMode('polygon')"
          >画不规则多边形</el-button
        >
        <el-button
          size="small"
          :type="mode === 'triangle' ? 'primary' : 'default'"
          @click="setMode('triangle')"
          >画三角形</el-button
        >
        <el-button size="small" type="success" @click="saveGeometries"
          >保存并打印数据</el-button
        >
        <el-button size="small" type="warning" @click="clearAll"
          >清空全部</el-button
        >
      </el-button-group>
    </div>

    <CesiumViewer
      ref="viewerComp"
      :options="viewerOptions"
      :camera="camera"
      :homeZoomOutFactor="0.3"
    >
      <template #entities>
        <!-- 绘制产生的实体将直接通过 viewer.entities 管理，这里不放子实体 -->
      </template>
    </CesiumViewer>
  </div>
</template>

<script setup>
// 页面：Cesium 进阶绘制（鼠标左键交互）
import { ref, onMounted, nextTick, onBeforeUnmount } from "vue";
import * as Cesium from "cesium";
import CesiumViewer from "@/components/cesium/CesiumViewer.vue";
import { ElMessage } from "element-plus";

// 模板 ref：CesiumViewer 组件与底层 viewer 实例
const viewerComp = ref(null);
const viewer = ref(null);

// Viewer 配置与初始相机
const viewerOptions = {
  animation: false,
  baseLayerPicker: false,
  geocoder: false,
  timeline: false,
  fullscreenButton: true,
  sceneModePicker: true,
};
const camera = {
  lon: 104.195397,
  lat: 35.86166,
  height: 12000000,
  heading: 0,
  pitch: -45,
  roll: 0,
};

// 当前模式：measure/rectangle/circle/ellipse/polygon/triangle/none
const mode = ref("measure");

// 状态数据：正在绘制的点列、生成的实体集合
const tempPositions = ref([]); // 正在绘制的坐标点（{lon,lat,height}）
const entities = ref([]); // 已生成的实体（保存打印）

// 事件处理器与临时绘制对象
let handler = null; // Cesium.ScreenSpaceEventHandler
let tempEntity = null; // 正在绘制中的临时实体（比如临时线）

// 统一绑定事件，重复调用会先销毁旧的 handler 再重绑
function bindEvents() {
  const v = viewer.value;
  if (!v) return;
  if (handler) {
    try {
      handler.destroy();
    } catch (_) {}
    handler = null;
  }
  // 创建事件处理器
  handler = new Cesium.ScreenSpaceEventHandler(v.scene.canvas);
  // 掉左键事件
  handler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  // 掉鼠标移动事件
  handler.setInputAction(onMouseMove, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  // 掉右键事件
  handler.setInputAction(finishShape, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  // 禁用浏览器右键菜单，避免抢占焦点导致交互失效
  try {
    v.scene.canvas.oncontextmenu = (e) => {
      e.preventDefault && e.preventDefault();
      return false;
    };
  } catch (_) {}
}

function setMode(m) {
  mode.value = m;
  resetTemp();
}

function resetTemp() {
  tempPositions.value = [];
  const v = viewer.value;
  if (v && tempEntity) {
    v.entities.remove(tempEntity);
    tempEntity = null;
  }
}

// 保存：打印所有已生成实体的几何数据（JSON），并附上字段中文说明
function saveGeometries() {
  const explainMap = {
    measure: {
      type: "类型（measure=测距）",
      positions:
        "折线节点数组，元素为 {lon 经度(度), lat 纬度(度), height 高度(米)}",
      length_m: "总长度（米，近似值）",
    },
    rectangle: {
      type: "类型（rectangle=矩形）",
      coordinates: "矩形区域（经纬矩形），WGS84 度制",
    },
    circle: {
      type: "类型（circle=圆）",
      center: "圆心 {lon 经度(度), lat 纬度(度), height 高度(米)}",
      radius: "半径（米）",
    },
    ellipse: {
      type: "类型（ellipse=椭圆）",
      center: "椭圆中心 {lon 经度(度), lat 纬度(度), height 高度(米)}",
      semiMinorAxis: "短轴（米）",
      semiMajorAxis: "长轴（米）",
    },
    polygon: {
      type: "类型（polygon=不规则多边形）",
      positions:
        "多边形顶点数组，元素为 {lon 经度(度), lat 纬度(度), height 高度(米)}",
    },
    triangle: {
      type: "类型（triangle=三角形）",
      positions:
        "三角形顶点数组（3个点），元素为 {lon 经度(度), lat 纬度(度), height 高度(米)}",
    },
  };
  const data = entities.value.map((e) => ({
    ...e.__data__,
    字段说明: explainMap[e.__data__?.type] || {},
  }));
  // 打印到控制台
  console.log("绘制结果：", JSON.stringify(data, null, 2));
  ElMessage && ElMessage.success("已在控制台打印绘制数据");
}

// 清空全部绘制（包括临时与已生成）
function clearAll() {
  const v = viewer.value;
  if (v) {
    // 移除所有已生成实体
    entities.value.forEach((ent) => {
      try {
        v.entities.remove(ent);
      } catch (_) {}
    });
  }
  entities.value = [];
  resetTemp();
  // 重新绑定一次交互，确保清空后仍可继续绘制
  bindEvents();
}

onMounted(() => {
  nextTick(() => {
    if (viewerComp.value && typeof viewerComp.value.getViewer === "function") {
      viewer.value = viewerComp.value.getViewer();
    }
    const v = viewer.value;
    if (!v) return;
    // 初始化事件处理器并屏蔽右键菜单
    bindEvents();
  });
});

onBeforeUnmount(() => {
  if (handler) {
    handler.destroy();
    handler = null;
  }
});

function pickLonLat(movement) {
  const v = viewer.value;
  if (!v) return null;
  const cartesian = v.camera.pickEllipsoid(
    movement.position || movement.endPosition,
    v.scene.globe.ellipsoid
  );
  if (!cartesian) return null;
  const c = Cesium.Cartographic.fromCartesian(cartesian);
  return {
    lon: Cesium.Math.toDegrees(c.longitude),
    lat: Cesium.Math.toDegrees(c.latitude),
    height: 0,
  };
}

function onLeftClick(movement) {
  // 左键：根据模式绘制图形 p是鼠标点击的坐标
  const p = pickLonLat(movement);
  if (!p) return;
  // 这是测距模式
  if (mode.value === "measure") handleMeasureClick(p);
  // 这是矩形模式
  else if (mode.value === "rectangle") handleRectangleClick(p);
  // 这是圆模式
  else if (mode.value === "circle") handleCircleClick(p);
  // 这是椭圆模式
  else if (mode.value === "ellipse") handleEllipseClick(p);
  // 这是多边形模式
  else if (mode.value === "polygon") handlePolygonClick(p);
  // 这是三角形模式
  else if (mode.value === "triangle") handleTriangleClick(p);
}

function onMouseMove(movement) {
  const p = pickLonLat(movement);
  if (!p) return;
  if (mode.value === "measure") previewMeasure(p);
  else if (mode.value === "rectangle") previewRectangle(p);
  else if (mode.value === "circle") previewCircle(p);
  else if (mode.value === "ellipse") previewEllipse(p);
  else if (mode.value === "polygon") previewPolygon(p);
  else if (mode.value === "triangle") previewTriangle(p);
}

function finishShape() {
  const v = viewer.value;
  if (!v) return;
  // 右键：根据模式完成图形
  if (mode.value === "measure") completeMeasure();
  else if (mode.value === "rectangle") completeRectangle();
  else if (mode.value === "circle") completeCircle();
  else if (mode.value === "ellipse") completeEllipse();
  else if (mode.value === "polygon") completePolygon();
  else if (mode.value === "triangle") completeTriangle();
}

// ========== 测距（折线 + 长度） ==========
function handleMeasureClick(p) {
  tempPositions.value.push(p);
  if (tempPositions.value.length === 1) {
    // 创建临时线
    const v = viewer.value;
    tempEntity = v.entities.add({
      polyline: {
        positions: new Cesium.CallbackProperty(
          () =>
            Cesium.Cartesian3.fromDegreesArray(
              tempPositions.value.flatMap((s) => [s.lon, s.lat])
            ),
          false
        ),
        width: 3,
        material: Cesium.Color.YELLOW,
      },
    });
  }
}
function previewMeasure(p) {
  if (!tempPositions.value.length) return;
  const arr = [...tempPositions.value, p];
  const v = viewer.value;
  if (tempEntity && tempEntity.polyline) {
    tempEntity.polyline.positions = new Cesium.CallbackProperty(
      () =>
        Cesium.Cartesian3.fromDegreesArray(arr.flatMap((s) => [s.lon, s.lat])),
      false
    );
  }
}
function completeMeasure() {
  if (tempPositions.value.length < 2) {
    resetTemp();
    return;
  }
  const v = viewer.value;
  const degrees = tempPositions.value.flatMap((p) => [p.lon, p.lat]);
  // 固化实体
  const entity = v.entities.add({
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray(degrees),
      width: 3,
      material: Cesium.Color.ORANGE,
    },
  });
  // 计算长度（平面近似）
  let total = 0;
  for (let i = 1; i < tempPositions.value.length; i++) {
    const a = Cesium.Cartesian3.fromDegrees(
      tempPositions.value[i - 1].lon,
      tempPositions.value[i - 1].lat
    );
    const b = Cesium.Cartesian3.fromDegrees(
      tempPositions.value[i].lon,
      tempPositions.value[i].lat
    );
    total += Cesium.Cartesian3.distance(a, b);
  }
  entity.__data__ = {
    type: "measure",
    positions: tempPositions.value,
    length_m: Math.round(total),
  };
  entities.value.push(entity);
  resetTemp();
}

// ========== 矩形 ==========
function handleRectangleClick(p) {
  tempPositions.value.push(p);
}
function previewRectangle(p) {
  if (tempPositions.value.length !== 1) return;
  const a = tempPositions.value[0];
  const b = p;
  const rect = Cesium.Rectangle.fromDegrees(
    Math.min(a.lon, b.lon),
    Math.min(a.lat, b.lat),
    Math.max(a.lon, b.lon),
    Math.max(a.lat, b.lat)
  );
  const v = viewer.value;
  if (!tempEntity) {
    tempEntity = v.entities.add({
      rectangle: {
        coordinates: rect,
        material: Cesium.Color.fromCssColorString("rgba(0,229,255,0.25)"),
        outline: true,
        outlineColor: Cesium.Color.CYAN,
      },
    });
  } else {
    tempEntity.rectangle.coordinates = rect;
  }
}
function completeRectangle() {
  if (tempPositions.value.length !== 1 || !tempEntity) {
    resetTemp();
    return;
  }
  // 固化数据
  tempEntity.__data__ = {
    type: "rectangle",
    coordinates: tempEntity.rectangle.coordinates.getValue(),
  };
  entities.value.push(tempEntity);
  tempEntity = null;
  tempPositions.value = [];
}

// ========== 圆 ==========
function handleCircleClick(p) {
  tempPositions.value.push(p);
}
function previewCircle(p) {
  if (tempPositions.value.length !== 1) return;
  const center = tempPositions.value[0];
  const centerC = Cesium.Cartesian3.fromDegrees(center.lon, center.lat);
  const edgeC = Cesium.Cartesian3.fromDegrees(p.lon, p.lat);
  const radius = Cesium.Cartesian3.distance(centerC, edgeC);
  const v = viewer.value;
  if (!tempEntity) {
    tempEntity = v.entities.add({
      position: Cesium.Cartesian3.fromDegrees(center.lon, center.lat),
      ellipse: {
        semiMinorAxis: radius,
        semiMajorAxis: radius,
        material: Cesium.Color.fromCssColorString("rgba(255,165,0,0.25)"),
        outline: true,
        outlineColor: Cesium.Color.ORANGE,
      },
    });
  } else {
    tempEntity.ellipse.semiMinorAxis = radius;
    tempEntity.ellipse.semiMajorAxis = radius;
    tempEntity.position = Cesium.Cartesian3.fromDegrees(center.lon, center.lat);
  }
}
function completeCircle() {
  if (tempPositions.value.length !== 1 || !tempEntity) {
    resetTemp();
    return;
  }
  // 固化数据
  const ellipse = tempEntity.ellipse;
  tempEntity.__data__ = {
    type: "circle",
    center: tempPositions.value[0],
    radius: ellipse.semiMajorAxis.getValue
      ? ellipse.semiMajorAxis.getValue()
      : ellipse.semiMajorAxis,
  };
  entities.value.push(tempEntity);
  tempEntity = null;
  tempPositions.value = [];
}

// ========== 椭圆 ==========
function handleEllipseClick(p) {
  tempPositions.value.push(p);
}
function previewEllipse(p) {
  if (tempPositions.value.length !== 1) return;
  const center = tempPositions.value[0];
  const centerC = Cesium.Cartesian3.fromDegrees(center.lon, center.lat);
  const edgeC = Cesium.Cartesian3.fromDegrees(p.lon, p.lat);
  const radius = Cesium.Cartesian3.distance(centerC, edgeC);
  const v = viewer.value;
  if (!tempEntity) {
    tempEntity = v.entities.add({
      position: Cesium.Cartesian3.fromDegrees(center.lon, center.lat),
      ellipse: {
        semiMinorAxis: radius * 0.6,
        semiMajorAxis: radius,
        material: Cesium.Color.fromCssColorString("rgba(0,255,127,0.25)"),
        outline: true,
        outlineColor: Cesium.Color.LIME,
      },
    });
  } else {
    tempEntity.ellipse.semiMinorAxis = radius * 0.6;
    tempEntity.ellipse.semiMajorAxis = radius;
    tempEntity.position = Cesium.Cartesian3.fromDegrees(center.lon, center.lat);
  }
}
function completeEllipse() {
  if (tempPositions.value.length !== 1 || !tempEntity) {
    resetTemp();
    return;
  }
  const ellipse = tempEntity.ellipse;
  tempEntity.__data__ = {
    type: "ellipse",
    center: tempPositions.value[0],
    semiMinorAxis: ellipse.semiMinorAxis.getValue
      ? ellipse.semiMinorAxis.getValue()
      : ellipse.semiMinorAxis,
    semiMajorAxis: ellipse.semiMajorAxis.getValue
      ? ellipse.semiMajorAxis.getValue()
      : ellipse.semiMajorAxis,
  };
  entities.value.push(tempEntity);
  tempEntity = null;
  tempPositions.value = [];
}

// ========== 多边形 ==========
function handlePolygonClick(p) {
  tempPositions.value.push(p);
  const v = viewer.value;
  if (!tempEntity) {
    tempEntity = v.entities.add({
      polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
          const arr = tempPositions.value.flatMap((s) => [s.lon, s.lat, 0]);
          return new Cesium.PolygonHierarchy(
            Cesium.Cartesian3.fromDegreesArrayHeights(arr)
          );
        }, false),
        material: Cesium.Color.fromCssColorString("rgba(0,229,255,0.25)"),
        outline: true,
        outlineColor: Cesium.Color.CYAN,
      },
    });
  }
}
function previewPolygon(p) {
  if (!tempEntity || !tempEntity.polygon) return;
  const arr = [...tempPositions.value, p].flatMap((s) => [s.lon, s.lat, 0]);
  tempEntity.polygon.hierarchy = new Cesium.CallbackProperty(
    () =>
      new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArrayHeights(arr)
      ),
    false
  );
}
function completePolygon() {
  if (!tempEntity || tempPositions.value.length < 3) {
    resetTemp();
    return;
  }
  // 固化数据
  tempEntity.__data__ = {
    type: "polygon",
    positions: [...tempPositions.value],
  };
  entities.value.push(tempEntity);
  tempEntity = null;
  tempPositions.value = [];
}

// ========== 三角形（多边形特化：3个点） ==========
function handleTriangleClick(p) {
  // 三角形点击三次可右键结束；也允许右键提前结束但至少三个点
  tempPositions.value.push(p);
  const v = viewer.value;
  if (!tempEntity) {
    tempEntity = v.entities.add({
      polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
          const arr = tempPositions.value.flatMap((s) => [s.lon, s.lat, 0]);
          return new Cesium.PolygonHierarchy(
            Cesium.Cartesian3.fromDegreesArrayHeights(arr)
          );
        }, false),
        material: Cesium.Color.fromCssColorString("rgba(255,0,0,0.2)"),
        outline: true,
        outlineColor: Cesium.Color.RED,
      },
    });
  }
}
function previewTriangle(p) {
  if (!tempEntity || !tempEntity.polygon) return;
  const arr = [...tempPositions.value, p]
    .slice(0, 3)
    .flatMap((s) => [s.lon, s.lat, 0]);
  tempEntity.polygon.hierarchy = new Cesium.CallbackProperty(
    () =>
      new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArrayHeights(arr)
      ),
    false
  );
}
function completeTriangle() {
  if (!tempEntity || tempPositions.value.length < 3) {
    resetTemp();
    return;
  }
  // 仅取前三个点构成三角形
  const tri = tempPositions.value.slice(0, 3);
  tempEntity.__data__ = { type: "triangle", positions: tri };
  entities.value.push(tempEntity);
  tempEntity = null;
  tempPositions.value = [];
}
</script>

<style scoped>
.page-wrap {
  position: relative;
  width: 100%;
  height: 100%;
}
.toolbar {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 20;
  background: rgba(255, 255, 255, 0.9);
  padding: 6px 8px;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
</style>
